/**
 * @author attilax 1466519819@qq.com
 * @version  c0
 * Copyright 2013 attilax reserved.
 * All content (including but not limited to text, pictures, etc.) have copyright restrictions, the note license.
 * all the software source code  copyright belongs to the original owner.
 * Creative Commons protocol use please follow the "sign for non-commercial use consistent"; we do not welcome the large-scale duplication, and all rights reserved.
 * Commercial sites or unauthorized media may not copy software source code.
 **/

package com.mijie.homi.search.service.index;

import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import m.secury.callbackItfs;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.log4j.Logger;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.FieldType;
import org.apache.lucene.document.LongField;
import org.apache.lucene.document.StringField;
import org.apache.lucene.index.FieldInvertState;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.similarities.DefaultSimilarity;
import org.apache.lucene.search.similarities.Similarity;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.NIOFSDirectory;
import org.apache.lucene.util.Version;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.wltea.analyzer.lucene.IKAnalyzer;

import com.mijie.core.ApplicationProperties;
import com.mijie.homi.common.domain.SearchResult;
import com.mijie.homi.common.domain.mood.Mood;
import com.mijie.homi.common.domain.user.User;
import com.mijie.homi.common.domain.user.UserExtInfo;
import com.mijie.homi.common.util.HomiUtil;
import com.mijie.homi.search.api.IdefaultMethod;
import com.mijie.homi.search.api.TopicSearchApi;
import com.mijie.homi.search.dao.mood.MoodDao;
import com.mijie.homi.search.dao.user.UserExtInfoDao;
import com.mijie.homi.search.domain.user.MoodUser;
import com.mijie.homi.search.service.mood.MoodService;
import com.mijie.homi.search.service.user.FriendSerivce;
import com.mijie.homi.search.service.user.UserExtInfoService;
import com.mijie.homi.search.service.user.UserService;
import com.mijie.homi.search.util.DbNdsController;
import com.mijie.homi.search.util.Dbcontroller;
import com.mijie.homi.search.util.Dbcontroller_local;
import com.mijie.homi.search.util.Levenshtein;
import com.mijie.homi.search.util.tryX;
import com.mijie.homi.search.util.god;
import com.mijie.homi.search.util.js;
import com.mijie.homi.search.util.listUtil;
import com.mijie.homi.search.util.mycfg;
import com.mijie.homi.search.util.pagingController;
import com.mijie.homi.search.util.securyInt;
import com.mijie.homi.search.util.strUtil;
import com.mijie.homi.search.util.utf8编码;

import com.mijie.query.fulltxtControllor;
import com.mijie.query.sincinController;
import com.mijie.test.tLog4j;
import com.mijie.util.DateUtil;
import com.mijie.util.GeoUtil;

/**
 * @author attilax 1466519819@qq.com
 * @version c0
 **/
@SuppressWarnings( { "unchecked", "unused", "static-access" })
@Service
public class MoodUserIndexService extends AbstractIndexService {

	@Autowired
	private UserExtInfoDao uedao;

	@Autowired
	private MoodDao mood_dao;

	@Autowired
	public MoodService moodService;
	@Autowired
	private UserService userService;
	@Autowired
	private UserExtInfoService userExtInfoService;
	@Autowired
	private FriendSerivce friendService;

	public static Logger logger = Logger.getLogger(MoodUserIndexService.class);
	public static Logger loggerT = Logger.getLogger("loggerT");
	private static Version version = Version.LUCENE_43;
	private static Analyzer ikAnalyzer = new IKAnalyzer(true);
	private static String moodUserIndexDir = ApplicationProperties
			.get("resource.path")
			+ ApplicationProperties.get("mooduser.index.home");

	@Override
	/**
	 * @author attilax 1466519819@qq.com
	 * @version  c0
	 **/
	public Analyzer getAnalyzer() {
		return ikAnalyzer;
	}

	@Override
	/**
	 * @author attilax 1466519819@qq.com
	 * @version  c0
	 **/
	public String getIndexDir() {
		return moodUserIndexDir;
	}

	@Override
	protected void reIndexBefore() {

	}

	static FieldType dontStoreButTokenized = new FieldType();
	static {
		dontStoreButTokenized.setIndexed(true);
		dontStoreButTokenized.setStored(false);
		dontStoreButTokenized.setTokenized(true);
		dontStoreButTokenized.freeze();
	}

	private Similarity similarity = new DefaultSimilarity() {

		@Override
		/**
		 * @author attilax 1466519819@qq.com
		 * @version  c0
		 **/
		public float tf(float freq) {
			return 1f;
		}

		@Override
		/**
		 * @author attilax 1466519819@qq.com
		 * @version  c0
		 **/
		public float idf(long docFreq, long numDocs) {
			return 1f;
		}

		@Override
		/**
		 * @author attilax 1466519819@qq.com
		 * @version  c0
		 **/
		public float queryNorm(float sumOfSquaredWeights) {
			return 1f;
		}

		@Override
		/**
		 * @author attilax 1466519819@qq.com
		 * @version  c0
		 **/
		public float lengthNorm(FieldInvertState state) {
			return 1f;
		}

		@Override
		/**
		 * @author attilax 1466519819@qq.com
		 * @version  c0
		 **/
		public float sloppyFreq(int distance) {
			return 1f;
		}
	};
	public String problemlib = "problemlib";

	@Autowired
	public dbc4Ibatis dbc4Ibatis;

	@Override
	protected void index() throws Exception {
		if (TopicIndexService.myPc())
			return;
		long s = System.currentTimeMillis();
		Date indexStartAt = new Date();
		IndexWriterConfig config = new IndexWriterConfig(version,
				getAnalyzer());
		config.setOpenMode(OpenMode.CREATE);
		config.setSimilarity(similarity);
		long currentTimeMillis = System.currentTimeMillis();
		String indexDirpath = getIndexDir() + currentTimeMillis;
		File indexDir = new File(indexDirpath);
		Directory topicDir = new NIOFSDirectory(indexDir);
		IndexWriter indexWriter = new IndexWriter(topicDir, config);
		logger
				.info("=========================index mood user begin!!===============================");
		logger.info("mood index file -> " + indexDir.getAbsolutePath());
		int limit = 1000;
		Document doc = null;
		int count = 0;
		int offset = 0;
		StringBuilder token = new StringBuilder();
		int minuteInterval = 0;
		List<MoodUser> list = null;
		HashSet<String> keywords = new HashSet<String>();
		StringBuilder keyword = new StringBuilder();
		Field keyField = null;
		while (true) {
			list = userService.listRecentlyLoginMoodUser(DateUtil.getPreDay(7,
					true), offset, limit);
			if (list.isEmpty())
				break;
			offset += limit;
			for (MoodUser user : list) {
				if (user.getLastLoginAt() == null)
					continue;
				doc = new Document();
				keywords.clear();
				keyword.setLength(0);
				getKeywords(user.getMoodContent(), keywords);
				if (keywords.isEmpty())
					continue;

				for (String kw : keywords) {
					keyword.append(kw).append(" ");
				}

				doc.add(new Field("moodContent", keyword.toString(),
						dontStoreButTokenized));
				doc.add(new LongField("moodId", user.getMoodId(),
						LongField.TYPE_STORED));
				doc.add(new StringField("mood",
						String.valueOf(user.getMood()), Store.NO));
				doc.add(new StringField("gender", String.valueOf(user
						.getGender()), Store.NO));
				doc.add(new StringField("userId", String.valueOf(user
						.getUserId()), Store.YES));
				doc.add(new LongField("lastLoginAt", user.getLastLoginAt()
						.getTime(), LongField.TYPE_STORED));
				indexWriter.addDocument(doc);
			}
		}
		indexWriter.commit();
		indexWriter.close();
		indexDone(indexDir);
		long e = System.currentTimeMillis();
		logger
				.info("=========================index mood user done!!===============================");
	}

	/**
	 * @author attilax 1466519819@qq.com
	 * @version c0
	 **/
	public String getKeywords(String str, HashSet<String> dest) {
		StringReader reader = new StringReader(str);
		StringBuilder sb = new StringBuilder();
		Integer freq = null;
		String token = null;
		String[] natures = null;
		TokenStream ts = null;
		boolean clearDest = false;
		try {
			ts = getAnalyzer().tokenStream(str, reader);
			CharTermAttribute termAtt = ts
					.getAttribute(CharTermAttribute.class);
			ts.reset();
			while (ts.incrementToken()) {
				token = termAtt.toString();
				if (token.length() > 1) {
					if (dest == null) {
						clearDest = true;
						dest = new HashSet<String>();
					}
					if (dest.add(token))
						sb.append(token).append(" ");
				}
			}
		} catch (IOException e) {
			logger.error(e.getMessage(), e);
		} finally {
			if (clearDest)
				dest.clear();
			if (ts != null) {
				try {
					ts.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		}
		return sb.toString();
	}

	enum Seasons {
		winter
	}

	/**
	 * 
	 "id": "354308", "content": "因为 爱情 家庭 孩子 自由 老公 出轨 吵架 打架", "匹配度": "33.53%",
	 * "g": "1", "pipeidu": 33.52922, "情绪分类": "负面", "人物关系":"[{\"num\":2,\"name\":\"夫妻关系\"},{\"num\":1,\"name\":\"恋爱男女\"},{\"num\":1,\"name\":\"孩子教育\"}]"
	 * , "事件":"[{\"num\":1,\"event\":\"0011_第三者\"},{\"num\":1,\"event\":\"0005_吵架\"},{\"num\":1,\"event\":\"0006_打架\"},{\"num\":1,\"event\":\"0001_追求\"}]"
	 * , "来源": "心情库", "filt": "爱情 家庭 孩子 自由 老公 出轨 吵架 打架", "filt_ini":
	 * "爱情 家庭 孩子 自由 老公 出轨 吵架 打架"
	 * 
	 * 
	 * "avatar":"avatar/1340693505368190000.jpg", "gender":0, 　　　"userId":3,
	 * 　　　"lastLoginAt":3242343, 　　　"mood":2, 　　　"moodContent":"sdfds",
	 * 　　　"moodProtected":"false", 　　　"nickName":"vison", 　　　"match":90,
	 * 　　　"distance ":0, 　　　" idxf":"34324234"
	 */
	/**
	 * @author attilax 1466519819@qq.com
	 * @version c0
	 **/
	// @SuppressWarnings("unchecked")
	@js("匹配主方法")
	public SearchResult match(String idxf, int offset, int limit, int userId,
			int gender) throws Exception {

		try {

			词库初始化: fulltxtControllor.ini_fentsiControllerX();
			@js("获取最近一条消息，心情或者问题")
			Mood mood = moodService.getRecentlyMoodNprblm(userId);
		//	int  ttt=Integer.parseInt( mood.getContent());
		// String t = mood.getContent();
			if (mood != null) {
				// cb23
				List<String> moodIds_li = new ArrayList<String>();
				List<String> prblmIds_li = new ArrayList<String>();
				// List<Object> prblms_li = new ArrayList<Object>();
				// List<Object> moods_li = new ArrayList<Object>();
				Map<String, Map> moods_mp = new HashMap<String, Map>();
				Map<String, Map> prblms_mp = new HashMap<String, Map>();
				Map<String, Map> msgs_mp = new HashMap<String, Map>();
				List<Object> block_sincin = new ArrayList<Object>();

				/**
				 * all mood problm
				 */
				// Map<String, Map> moods_map = new HashMap<String, Map>();
				//o1g
				String s=securyInt.getString(mood.getContent()).trim();
				if(s.length()==0)
					return  (SearchResult) new IdefaultMethod() {
						
						@Override
						public Object $(Object param) {
							SearchResult empty = new SearchResult();
							empty.setResult(new JSONArray());
							return empty;
						}
					}.$(1);
					

				String mood_cn = sincinController.getMood_cn(mood.getMood());
				  s = mood_cn + "@"
						+ securyInt.getString(mood.getContent());
				fulltxtControllor c = new fulltxtControllor();
				c.wordlibcache = true;
				c.exceptUid = userId;
				开始查询: c.search(s);
				List<Map> r = c.searchResult_li;
				int n = 0;
				// JSONArray ja=new JSONArray();
				List<Map> r2 = new ArrayList<Map>();
				// List<Integer> li2=li.subList(from, from+pagesize);
				初步构建map: for (Map m : r) {
					n++;

					Map m4cp = new HashMap<String, Object>();
					// m4cp.put("match", m.get("pipeidu"));

					m4cp.put("match", securyInt.getInt(m.get("pipeidu"), 90));

					// new Float((Float) m.get("pipeidu"))
					// .intValue());
					m4cp.put("gender", 1);
					m4cp.put("mood", 1);
					m4cp.put("userId", 277932);
					m4cp
							.put("avatar",
									"nullavatar/small/812a2b13-aa84-40f6-a1ae-c28a5d29448d.jpg");
					m4cp.put("distance", 0);
					m4cp.put("nickName", "");
					m4cp.put("moodContent", m.get("content"));
					m4cp.put("moodVisibility", 1);
					m4cp.put("lastLoginAt", 1386875326000l);
					m4cp.put("moodProtected", false);
					m4cp.put("idxf", 1387449318881l);

					if (n <= 200) {
						r2.add(m4cp);
						String fromx = securyInt.getString(m.get("fromx"),
								sincinController.sincinlib);
						;
						String id = (String) m.get("id");
						if (fromx.equals(problemlib)) {

							prblmIds_li.add(id);
							// prblm_li.add(m4cp);
							msgs_mp.put("pr" + id, m4cp);
							prblms_mp.put(id, m4cp);

						} else {

							moodIds_li.add(id);
							msgs_mp.put("sc" + id, m4cp);
							moods_mp.put(id, m4cp);

						}
						// moods_map.put(id, m4cp);

						// msg_li.add(m4cp);
					} else
						break;
				}
				List del_sincin_markDelete_set = new ArrayList<String>();
				Set moodIds_except = new HashSet<String>();
				List msg_del_by_gender = new ArrayList<Object>();
				Set prblmIds_except = new HashSet<String>();
				List del_Msg_ByHeminLen = new ArrayList<Object>(); // nbt
				Set userID_deduli_set = new HashSet<String>();
				List msg_wait_del_byDuliUser = new ArrayList<Object>();
				// o12
				List msg_wait_hid_byAnonymosPrblm = new ArrayList<Object>();
				// o12
				List msg_wait_hid_byMktDelPrblm = new ArrayList<Object>();
				// cb23
				String sql = "";
				String userpic = "";
				Dbcontroller dbc = new DbNdsController();
				// o1e
				List cinsyv_bfu = new ArrayList<Object>();
				// if (moodIds_li.size() > 0)// cb24
				// {
				// String moodIds_str = listUtil.toString(moodIds_li, ",");
				//
				// sql =
				// "select *,u.id uid from mood m,user u  where  m.userid=u.id and m.id in (@ids) order by m.id desc limit 100";
				// sql =
				// "select *,u.id uid,e.lastloginat from mood m,user u,userExtInfo e  where  m.userid=u.id and u.id=e.id and m.id in (@ids) order by m.id desc limit 100";
				// sql = sql.replaceAll("@ids", moodIds_str);
				// logger.info(sql);
				// ResultSet rs = dbc.getrs(sql);
				// while (rs.next()) {
				// String id = rs.getString("id");
				// // nbp
				// String markDelete_s = rs.getString("markDelete");
				// if (markDelete_s.equals("1")) {
				// del_sincin_markDelete_set.add(id);
				// }
				// // /
				//
				// Map mood_m = msgs_mp.get("sc" + id);
				// // nbt
				// String txt_frmMoodlib = securyInt.getString(rs
				// .getString("content"));
				// del_by_heminLen(del_Msg_ByHeminLen, rs, mood_m);
				// //
				// mood_m.put("moodContent", txt_frmMoodlib);
				// mood_m.put("mood", rs.getInt("mood"));
				// mood_m.put("userId", rs.getLong("uid"));
				// userpic = "http://mijietest.f3322.org:8282/res/";
				// mood_m.put("avatar", userpic + rs.getString("avatar"));
				//
				// mood_m.put("lastLoginAt", rs.getTimestamp("lastloginat")
				// .getTime());
				// mood_m.put("nickName", rs.getString("nickName"));
				// mood_m.put("gender", rs.getInt("gender"));
				//
				// // tbn hide hide msg
				// int visibility = securyInt.getInt(rs
				// .getString("visibility"), 1);
				// if (visibility > 1) {
				// String id_md = god.getUUid4msg(mood_m.get("userId")
				// .toString(), mood_m.get("moodContent")
				// .toString(), mood_m.get("lastLoginAt")
				// .toString());
				// moodIds_except.add(id_md);
				// }
				// // /
				// // O11 obder by nenv
				// int nenv = securyInt.getInt(mood_m.get("gender"), 0);
				// if (gender != 0)
				// if (nenv != gender)
				// msg_del_by_gender.add(mood_m);
				//
				// // de duli user
				// String uid_s = String.valueOf(rs.getLong("uid"));
				// if (userID_deduli_set.contains(uid_s))
				// msg_wait_del_byDuliUser.add(mood_m);
				// userID_deduli_set.add(uid_s);
				//
				// // o12
				// int block = securyInt.getInt(rs.getString("block"), 0);
				// if (block == 1)
				// block_sincin.add(mood_m);
				// }
				// }
				//			
				// o17

				针对心情获取详细信息: if (moodIds_li.size() > 0)// cb24
				{
					// @js("针对心情获取详细信息")
					String moodIds_str = listUtil.toString(moodIds_li, ",");

					List<Map> moods_li = mood_dao.moodsByIds(moodIds_str);
					logger.info(sql);
					for (Map rs : moods_li) {
						String id = securyInt.getString(rs.get("id"));
						// nbp
						String markDelete_s = securyInt.getString(rs
								.get("markDelete"));
						if (markDelete_s.equals("1")) {
							del_sincin_markDelete_set.add(id);
						}
						// /

						Map mood_m = msgs_mp.get("sc" + id);
						// nbt
						String txt_frmMoodlib = securyInt.getString(rs
								.get("content"));
						del_by_heminLen(del_Msg_ByHeminLen, rs, mood_m);
						//
						mood_m.put("moodContent", txt_frmMoodlib);
						mood_m.put("mood", rs.get("mood"));
						mood_m.put("userId", rs.get("uid"));
						userpic = "http://mijietest.f3322.org:8282/res/";
						mood_m.put("avatar", userpic + rs.get("avatar"));

						Timestamp ts = (Timestamp) rs.get("lastloginat");
						mood_m.put("lastLoginAt", ts.getTime());

						// o19
						Timestamp ts_publishTime = (Timestamp) rs
								.get("createAt");
						mood_m.put("createAt", ts_publishTime.getTime());

						mood_m.put("nickName", rs.get("nickName"));
						mood_m.put("gender", rs.get("gender"));

						// tbn hide hide msg
						int visibility = securyInt.getInt(
								rs.get("visibility"), 1);
						if (visibility > 1) {
							String id_md = god.getUUid4msg(mood_m
									.get("userId").toString(), mood_m.get(
									"moodContent").toString(), mood_m.get(
									"lastLoginAt").toString());
							moodIds_except.add(id_md);
						}
						// /
						// O11 obder by nenv
						int nenv = securyInt.getInt(mood_m.get("gender"), 0);
						if (gender != 0)
							if (nenv != gender)
								msg_del_by_gender.add(mood_m);

						// de duli user
						String uid_s = String.valueOf(rs.get("uid"));
						if (userID_deduli_set.contains(uid_s))
							msg_wait_del_byDuliUser.add(mood_m);
						userID_deduli_set.add(uid_s);

						// o12
						int block = securyInt.getInt(rs.get("block"), 0);
						if (block == 1)
							block_sincin.add(mood_m);

						// o1e cinsyv bfu
						try {
							if (!sincinController.cinsyvMatch(mood_cn, rs
									.get("mood")))
								cinsyv_bfu.add(mood_m);
						} catch (Exception e) {
							logger.warn("cinsyv_bfu.add  " + god.getTrace(e));
						}
					}
				}
				针对问题TOPIC获取详细信息: if (prblmIds_li.size() > 0) // cb24
				{
					// dbc=dbc4Ibatis;
					String prblmIds_str = listUtil.toString(prblmIds_li, ",");
					// sql =
					// "select *,  e.lastloginat from topic m,user u ,userExtInfo e where  m.author=u.id   and u.id=e.id and m.id in (@ids) order by m.id desc limit 100";

					// select *,u.id uid,e.lastloginat from mood m,user
					// u,userExtInfo e where m.userid=u.id and u.id=e.id
					// sql = sql.replaceAll("@ids", prblmIds_str);
					logger.info(sql);
					ResultSet rs = dbc4Ibatis.getrs("getTopicsByIds",
							prblmIds_str);
					while (rs.next()) {
						String id = rs.getString("id");
						Map mood_m = msgs_mp.get("pr" + id);
						// o12
						String markDelete_s = rs.getString("markDelete");
						if (markDelete_s.equals("1")) {
							msg_wait_hid_byMktDelPrblm.add(mood_m);
						}

						// nbt
						String txt_fromPrblmLib = securyInt.getString(rs
								.getString("title"));

						add_set_del_by_heminLen(del_Msg_ByHeminLen, rs, mood_m);
						//
						// String txt_fromPrblmLib = rs.getString("title");
						mood_m.put("moodContent", txt_fromPrblmLib);
						mood_m.put("mood", 7);
						mood_m.put("userId", rs.getLong("author"));
						mood_m.put("avatar", userpic + rs.getString("avatar"));
						mood_m.put("lastLoginAt", rs.getTimestamp(
								"lastloginat").getTime());
						// o19
						Timestamp ts_publishTime = (Timestamp) rs
								.getTimestamp("createAt");
						mood_m.put("createAt", ts_publishTime.getTime());

						mood_m.put("nickName", rs.getString("nickName"));
						mood_m.put("gender", rs.getInt("gender"));
						// tbn hide hide msg
						int visibility = securyInt.getInt(rs
								.getString("visible"), 1);
						if (visibility > 1) {
							String id_md = god.getUUid4msg(mood_m
									.get("userId").toString(), mood_m.get(
									"moodContent").toString(), mood_m.get(
									"lastLoginAt").toString());
							moodIds_except.add(id_md);

						}
						// /
						// O11 obder by nenv
						int nenv = securyInt.getInt(mood_m.get("gender"), 0);
						if (gender != 0)
							if (nenv != gender)
								msg_del_by_gender.add(mood_m);

						// o12

						int anonymous = securyInt.getInt(rs
								.getString("anonymous"), 0);
						if (anonymous == 1)
							msg_wait_hid_byAnonymosPrblm.add(mood_m);

					}
				}

				dbc.close();

				// Nbo order by pipeidu,createAt ,ar only pipeidu
				try {

					按照时间排序: orderByCreateTime(r2);// @js("按照时间排序")

				} catch (Exception e) {
					logger.info(god.getTrace(e));
				}
				// nbp order by active user

				按照在线用户排序: r2 = order_by_active_user(r2);
				logger.info("  return all:" + r2.size());

				// ///
				List<Map> li3 = r2;
				// tbn hide not public
				li3 = exceptHide(li3, moodIds_except, prblmIds_except);
				// //
				// Nbo del prblm if sincin jenmye

				排除问题如果心情是正面: try {
					if (sincinController.isJenmyerSincin(mood.getMood()))
						li3 = del_prblm(prblmIds_li, li3, moods_mp);
				} catch (Exception e) {
					logger.info(god.getTrace(e));
				}

				// Nbp del sincin markDelete
				li3 = del_sincin_markDelete(del_sincin_markDelete_set, li3,
						moods_mp);

				// nbt del bpipei d sincinN prblm by hemin len
				排除不一致的消息: li3 = del_byHeminLen(del_Msg_ByHeminLen, li3);

				// o11
				li3 = delMsg_by_gender(msg_del_by_gender, li3);

				// o12 排除匿名标记删除，屏蔽的消息
				li3 = delMsg_by_byAnonymosPrblm(msg_wait_hid_byAnonymosPrblm,
						li3);
				li3 = delMsg_by_byMktDelPrblm(msg_wait_hid_byMktDelPrblm, li3);
				li3 = delMsg_block_sincin(block_sincin, li3);
				// o16
				根据消息ID查找不到结果的心情或问题_应该过滤掉: li3 = delMsg_dedw(li3);

				// o17 except uid
				排除自己的消息: li3 = except_self(li3, userId, msgs_mp, moodIds_li);

				// o1e cyvsyv bfu except
				/**
				* @author att 
				* 	   .----.
				* 	  / .--. \
				* 	 | (    ) |              ___...---.
				* 	  \ '--'  '----._..---"""___...---'`
				* 	   '-.--:------|_()---"""__ 
				* 	  / .--.  .----'`''---...__"""---..
				* 	 | (    ) |                """---''`
				* 	  \ '--' /
				* 	   '----'
				* 
				*/
				li3 = except_cinsyv_bfu(li3, cinsyv_bfu);

				// o11 duli user
				// de duli user
				userID_deduli_set = new HashSet<String>();
				msg_wait_del_byDuliUser = new ArrayList<Object>();
				for (Map m : li3) {

					String uid_s = String.valueOf(m.get("userId"));

					if (userID_deduli_set.contains(uid_s))
						msg_wait_del_byDuliUser.add(m);
					userID_deduli_set.add(uid_s);
				}

				排除重复用户: li3 = delMsg_by_byDuliUser(msg_wait_del_byDuliUser,
						li3);

				// List<Map> li3 =ftc. except_uidByMids(sincinIds_set, new
				// ArrayList<String>(), li3);

				// tbn paging.
				List<Map> li4 = pagingController.newPage(offset, limit, li3);
				li4 = countDistans(userId, li4);

				// nbt
				try {
					String snbt = JSONArray.fromObject(li4).toString(2);
					fulltxtControllor.logger_for_match_debug
							.info("---paginged " + snbt);
				} catch (Exception e) {
					fulltxtControllor.logger_for_match_debug.info(god
							.getTrace(e));
					logger.info(god.getTrace(e));
				}

				// li3=
				// //

				// //for test time long .
				try {
					String eventStrformat = JSONObject.fromObject(r2.get(0))
							.toString(2);
					logger.info(eventStrformat);
				} catch (Exception e) {
					logger.warn(god.getTrace(e));
				}

				// //

				// log
				List<String> li5 = new ArrayList<String>();
				for (Map m : li3) {
					li5.add((String) m.get("moodContent"));
					// li5.add((String) m.get("lastLoginAt"));

				}
				String eventStrformatx = JSONArray.fromObject(li5).toString(2);
				logger.info(eventStrformatx);
				// ///

				JSONArray json = JSONArray.fromObject(li4);
				SearchResult result = new SearchResult();
				result.setResult(json);

				return result;
			} // end if
			
		} catch (Exception e) {
			logger.error(god.getTrace(e));
		}
		SearchResult empty = new SearchResult();
		empty.setResult(new JSONArray());
		return empty;
	}

	public List<Map> except_cinsyv_bfu(List<Map> li3, final List<Map> cinsyvBfu) {
		if (1 == 1)
			return li3;

		final List lit = li3;
		// li3 = tryx(
		// 
		// new tryI() {
		//			
		//		 
		// Object itemWrap(Object t) {
		// try {
		// return item(t);
		// } catch (Exception e) {
		//					 
		// }
		// return t;
		// }
		//
		// @Override
		// public Object item(Object t) throws Exception {
		// for (Map m : cinsyvBfu) {
		// lit.remove(m);
		//				 
		// }
		// return t;
		// }
		// }
		//		
		// );
		// List li= (List) tryX.tryStart(new tryX() {
		//		 
		//			
		// @Override
		// public Object item(Object t) throws Exception {
		// for (Map m : cinsyvBfu) {
		// lit.remove(m);
		// }
		// return t;
		// }
		//			
		// public Object log(Object t)
		// {
		// logger.info(t);
		// return null;
		// // this. ==tryx
		// }
		// }
		// ).other();

		return lit;
	}

	private List<Map> tryx(tryI tryI) {
		// TODO Auto-generated method stub
		return null;
	}

	private Set js(String string) {
		// TODO Auto-generated method stub
		return null;
	}

	/**
	 * 排除本人
	 * 
	 * @param li3
	 * @param userId
	 * @param msgsMp
	 * @param moodIds_li
	 * @return
	 */
	protected List<Map> except_self(List<Map> li3, int userId,
			Map<String, Map> msgs_mp, List<String> moodIds_li) {
		try {
			fulltxtControllor ftc = new fulltxtControllor(0);
			ftc.exceptUid = userId;
			String moodids_s = listUtil.toString(moodIds_li);
			Dbcontroller dbcontroller = new DbNdsController();
			ftc.dbc_tbn = dbcontroller;
			Set<String> sincinIds_will_except = ftc.get_sincinIds_will_except(
					moodids_s, userId);
			dbcontroller.close();
			List<String> sincinIds_will_except_li = listUtil
					.toList(sincinIds_will_except);
			for (String sincinId : sincinIds_will_except_li) {
				Map m = msgs_mp.get("sc" + sincinId);
				li3.remove(m);
			}

		} catch (Exception e) {
			logger.warn(god.getTrace(e));
		}
		return li3;
	}
	@Autowired
	private SqlSessionTemplate sqlSession;
	/**
	 * 
	 * @param userId
	 * @param li4
	 * @return
	 */
	private List<Map> countDistans(int userId, List<Map> li) {
		
		try {
			UserExtInfo ui = uedao.getUserExtInfoByUserId(userId);
			List uids = new ArrayList<String>();
			for (Map m : li) {
				uids.add(securyInt.getString(m.get("userId"), "99999999"));
			}
			String uids_str = listUtil.toString(uids);

			String sql = "select getDistance(@long,@lati,longitude,latitude) distans,id from userExtInfo  where id in (@uids) limit 1000";
			sql = sql.replaceAll("@long", String.valueOf(ui.getLongitude()));
			sql = sql.replaceAll("@lati", String.valueOf(ui.getLatitude()));
			sql = sql.replaceAll("@uids", uids_str);
			logger.info(sql);
			Map u_dis_map = new HashMap<String, String>();
			Dbcontroller dbc = new DbNdsController();
			ResultSet rs = null;
			try{
			  rs = dbc.getrs(sql);
			  while (rs.next()) {
					u_dis_map.put(rs.getString("id"), rs.getString("distans"));
				}
				
			}catch (Exception e) {
				//o1f 
			    List<UserExtInfo> uei_li=this.sqlSession.selectList("getUserExtInfoByUserIds",uids_str);	
			    for (UserExtInfo ue : uei_li) {
			    	Double distanc=GeoUtil.getDistance(ui.getLongitude(), ui.getLatitude(), ue.getLongitude(), ue.getLatitude());
			    	u_dis_map.put( String.valueOf(ue.getId()), distanc.toString());
			    	
			    }
				
			}finally{
				dbc.close();
			}
			
			for (Map m : li) {
				String uid = securyInt.getString(m.get("userId"), "99999999");
				m.put("distance", securyInt.getDouble(u_dis_map.get(uid), 0));
			}
		} catch (Exception e) {
			logger.warn(god.getTrace(e));
			loggerT.warn(god.getTrace(e));
		}
		return li;
	}

	/**
	 * 根据消息ID查找不到结果的心情或问题，应该过滤掉
	 * 
	 * @param li3
	 * @return
	 */
	// @SuppressWarnings("unchecked")
	protected List<Map> delMsg_dedw(List<Map> li3) {
		try {
			List<Map> l_toDel = new ArrayList<Map>();
			// @SuppressWarnings("unused")
			List<Map> r = new ArrayList<Map>();
			for (Map m : li3) {
				int n = Integer.parseInt(m.get("userId").toString());
				if (n == 277932)
					l_toDel.add(m);
			}
			for (Map m : l_toDel) {
				li3.remove(m);
			}

		} catch (Exception e) {
			logger.warn(god.getTrace(e));
			// return li3;
		}
		return li3;
	}

	private List<Map> delMsg_block_sincin(List blockSincin, List<Map> li3) {

		return delMsg_by_byMktDelPrblm(blockSincin, li3);
	}

	protected List<Map> delMsg_by_byMktDelPrblm(
			List<Map> msgWaitHidByMktDelPrblm, List<Map> li3) {
		try {
			List<Map> r = new ArrayList<Map>();
			for (Map m : msgWaitHidByMktDelPrblm) {
				li3.remove(m);
			}
		} catch (Exception e) {
			logger.warn(god.getTrace(e));
		}
		return li3;
	}

	private List<Map> delMsg_by_byAnonymosPrblm(
			List<Map> msgWaitHidByAnonymosPrblm, List<Map> li3) {
		try {
			List<Map> r = new ArrayList<Map>();
			for (Map m : msgWaitHidByAnonymosPrblm) {
				li3.remove(m);
			}
		} catch (Exception e) {
			logger.warn(god.getTrace(e));
		}
		return li3;
	}

	private List<Map> delMsg_by_byDuliUser(List<Map> msgWaitDelByDuliUser,
			List<Map> li3) {
		try {
			List<Map> r = new ArrayList<Map>();
			for (Map m : msgWaitDelByDuliUser) {
				li3.remove(m);
			}
		} catch (Exception e) {
			logger.warn(god.getTrace(e));
		}
		return li3;
	}

	protected List<Map> delMsg_by_gender(List<Map> msgDelByGender,
			List<Map> li3) {
		try {
			List<Map> r = new ArrayList<Map>();
			for (Map m : msgDelByGender) {
				li3.remove(m);
			}
		} catch (Exception e) {
			logger.warn(god.getTrace(e));
		}
		return li3;
	}

	protected List<Map> del_byHeminLen(List<Map> delMsgByHeminLen,
			List<Map> li3) {
		try {
			List<Map> r = new ArrayList<Map>();
			for (Map m : delMsgByHeminLen) {

				li3.remove(m);

			}
		} catch (Exception e) {
			logger.warn(god.getTrace(e));
		}
		return li3;
	}

	public String add_set_del_by_heminLen(List del_Msg_ByHeminLen,
			ResultSet rs, Map mood_m) {
		try {
			String txt_frmMoodlib = strUtil.delPunctualion(securyInt
					.getString(rs.getString("title")));
			String txt_from_index = securyInt.getString(
					mood_m.get("moodContent")).replaceAll(" ", "");
			;
			Float syeosidu = Levenshtein.levenshtein(txt_from_index,
					txt_frmMoodlib);

			if (syeosidu < 0.8f)
				del_Msg_ByHeminLen.add(mood_m);
			return txt_frmMoodlib;
		} catch (Exception e) {
			logger.warn(god.getTrace(e));
		}
		return "";
	}

	private String del_by_heminLen(List del_Msg_ByHeminLen, ResultSet rs,
			Map mood_m) {
		try {
			String txt_frmMoodlib = strUtil.delPunctualion(securyInt
					.getString(rs.getString("content")));
			if (txt_frmMoodlib.contains("没钱了"))
				System.out.println("");
			String txt_from_index = securyInt.getString(
					mood_m.get("moodContent")).replaceAll(" ", "");
			;
			Float syeosidu = Levenshtein.levenshtein(txt_from_index,
					txt_frmMoodlib);

			if (syeosidu < 0.8f)
				del_Msg_ByHeminLen.add(mood_m);
			return txt_frmMoodlib;

		} catch (Exception e) {
			logger.warn(god.getTrace(e));
		}
		return "";
	}

	private String del_by_heminLen(List del_Msg_ByHeminLen, Map rs, Map mood_m) {
		try {
			String txt_frmMoodlib = strUtil.delPunctualion(securyInt
					.getString(rs.get("content")));
			if (txt_frmMoodlib.contains("没钱了"))
				System.out.println("");
			String txt_from_index = securyInt.getString(
					mood_m.get("moodContent")).replaceAll(" ", "");
			;
			Float syeosidu = Levenshtein.levenshtein(txt_from_index,
					txt_frmMoodlib);

			if (syeosidu < 0.8f)
				del_Msg_ByHeminLen.add(mood_m);
			return txt_frmMoodlib;

		} catch (Exception e) {
			logger.warn(god.getTrace(e));
		}
		return "";
	}

	protected List<Map> order_by_active_user(List<Map> r2) {
		try {
			String uids = listUtil.toString4liMap(r2, "userId");
			String sql = "SELECT id FROM `userExtInfo` where id in (@uid) and    lastLoginAt> date_sub(now(),interval 180 minute)";
			sql = sql.replace("@uid", uids);
			Dbcontroller dbc = new DbNdsController();
			String auids = dbc.getIds(sql);
			Set acUids = listUtil.toSet_splitComma(auids);
			dbc.close();

			List<Map> activeU = new ArrayList<Map>();
			List<Map> un_activeU = new ArrayList<Map>();
			for (Map m : r2) {
				String uid = m.get("userId").toString();
				if (acUids.contains(uid))
					activeU.add(m);
				else
					un_activeU.add(m);
			}

			List<Map> result = new ArrayList<Map>();
			result.addAll(activeU);
			result.addAll(un_activeU);
			return result;
		} catch (Exception e) {
			logger.warn(god.getTrace(e));
			return r2;
		}
	}

	/**
	 * nbp
	 * 
	 * @param delSincinMarkDeleteSet
	 * @param li3
	 * @param moodsMap
	 * @return
	 */
	protected List<Map> del_sincin_markDelete(
			List<String> delSincinMarkDeleteSet, List<Map> li3,
			Map<String, Map> moodsMap) {
		try {
			List<Map> r = new ArrayList<Map>();
			for (String msgId : delSincinMarkDeleteSet) {
				Map m = moodsMap.get(msgId);
				li3.remove(m);

			}
		} catch (Exception e) {
			logger.warn(god.getTrace(e));
		}
		return li3;

	}

	public List<Map> orderByCreateTime(List<Map> r2) {

		Collections.sort(r2, new Comparator<Map>() {
			public int compare(Map mapping1, Map mapping2) {
				Long crtm1 = (Long) mapping1.get("lastLoginAt");
				Float match1 = securyInt.getFloat(mapping1.get("match"), 70f);
				// System.out.println("mapping1:"+mapping1+"|"+mapping2);
				Long crtm2 = (Long) mapping2.get("lastLoginAt");
				Float match2 = securyInt.getFloat(mapping2.get("match"), 70f);
				// System.out.println( crtm1+"___"+crtm2);
				if (match1 > match2)
					return -1; // match1 > match2 is true
				else if (match1.equals(match2)) {
					// return 0;
					if (crtm1 > crtm2)
						return -1;
					if (crtm1.equals(crtm2))
						return 0;
					else
						return 1;
				} else
					return 1;
				// return mapping1.getValue().compareTo(mapping2.getValue());
			}
		});

		// log
		List<String> li5 = new ArrayList<String>();
		for (Map m : r2) {
			li5.add(m.get("match").toString());
			li5.add((String) m.get("moodContent"));
			li5.add(m.get("lastLoginAt").toString());

		}
		String eventStrformatx = JSONArray.fromObject(li5).toString(2);
		logger.info(eventStrformatx);
		return r2;
	}

	private List<Map> del_prblm(List<String> prblmIdsLi, List<Map> li3,
			Map<String, Map> moodsMap) {
		List<Map> r = new ArrayList<Map>();
		for (String msgId : prblmIdsLi) {
			Map m = moodsMap.get(msgId);
			li3.remove(m);

		}
		return li3;
	}

	private List<Map> exceptHide(List<Map> li3, Set moodIdsExcept,
			Set prblmIdsExcept) {
		List<Map> r = new ArrayList<Map>();
		for (Map m : li3) {
			String id_md = getUUid_mood(m);
			if (!moodIdsExcept.contains(id_md))
				if (!prblmIdsExcept.contains(id_md))
					r.add(m);
		}
		return r;
	}

	private String getUUid_mood(Map mood_m) {

		String id_md = god.getUUid4msg(mood_m.get("userId").toString(), mood_m
				.get("moodContent").toString(), mood_m.get("lastLoginAt")
				.toString());
		// moodIds_except.add(id);
		return id_md;
	}

	@utf8编码
	public SearchResult match_cb20(String idxf, int offset, int limit,
			int userId, int gender) throws Exception {
		Mood mood = moodService.getRecentlyMood(userId);
		if (mood != null) {
			userIdCacheInCurrentThread.set(userId);
			BooleanQuery query = new BooleanQuery();
			query.add(
					new TermQuery(new Term("userId", String.valueOf(userId))),
					Occur.MUST_NOT);
			if (gender == 1 || gender == 2) {
				query.add(new TermQuery(new Term("gender", String
						.valueOf(3 - gender))), Occur.MUST_NOT);
			}

			HashSet<String> keywords = new HashSet<String>();
			String buff = getKeywords(mood.getContent(), keywords);
			if (keywords.size() > 1) {
				moodKeywordCacheInCurrentThread.set(keywords);
				for (String key : keywords)
					query.add(new TermQuery(new Term("moodContent", key)),
							Occur.SHOULD);
			}

			Sort sort = new Sort(new SortField("lastLoginAt",
					SortField.Type.LONG, true));

			SearchResult result = search(similarity, idxf, offset, limit,
					query, sort);

			moodKeywordCacheInCurrentThread.remove();
			userIdCacheInCurrentThread.remove();
			return result;
		}
		SearchResult empty = new SearchResult();
		empty.setResult(new JSONArray());
		return null;
	}

	private ThreadLocal<HashSet<String>> moodKeywordCacheInCurrentThread = new ThreadLocal<HashSet<String>>() {
		@Override
		protected HashSet<String> initialValue() {
			return null;
		}
	};

	private ThreadLocal<Integer> userIdCacheInCurrentThread = new ThreadLocal<Integer>() {
		@Override
		protected Integer initialValue() {
			return null;
		}
	};

	@Override
	protected Object makeResultItem(String idxf, float socre, Document doc) {
		Set<String> keywords = moodKeywordCacheInCurrentThread.get();
		Mood mood = moodService.getMoodById(Long.parseLong(doc.get("moodId")));
		if (mood == null)
			return null;
		JSONObject json = new JSONObject();
		User user = userService.getUserById(Integer
				.parseInt(doc.get("userId")));
		UserExtInfo extInfo = userExtInfoService.getUserExtInfoByUserId(user
				.getId());
		json.accumulate("userId", user.getId());
		json.accumulate("avatar", HomiUtil.getRealUrl(user.getAvatar()));
		json.accumulate("gender", user.getGender());
		json.accumulate("mood", mood.getMood());
		json.accumulate("distance", 0);
		json.accumulate("nickName", user.getNickName());
		json.accumulate("moodContent", mood.getContent());
		json.accumulate("moodVisibility", mood.getVisibility());
		json.accumulate("lastLoginAt", doc.get("lastLoginAt"));
		// 可见度(1所有,2朋友,3私有)
		switch (mood.getVisibility()) {
		case 2:
			boolean flag = friendService.isFriend(user.getId(),
					userIdCacheInCurrentThread.get());
			if (!flag)
				flag = moodService.haveMoodViewPrivilege(
						userIdCacheInCurrentThread.get(), mood.getId());
			json.accumulate("moodProtected", !flag);
			break;
		case 3:
			boolean haveViewPrivilege = moodService.haveMoodViewPrivilege(
					userIdCacheInCurrentThread.get(), mood.getId());
			json.accumulate("moodProtected", !haveViewPrivilege);
			break;
		default:
			json.accumulate("moodProtected", false);
		}
		json
				.accumulate("match", computeMatchRate(keywords, mood
						.getContent()));
		// json.accumulate("match", socre*100);
		json.accumulate("idxf", idxf);
		return json;
	}

	/**
	 * @author attilax 1466519819@qq.com
	 * @version c0
	 **/
	private float computeMatchRate(Set<String> keywordsOfMyMoodContent,
			String target) {
		float match = 0f;
		float rate = 1f;
		if (keywordsOfMyMoodContent != null
				&& !keywordsOfMyMoodContent.isEmpty() && target != null
				&& !target.trim().isEmpty()) {
			StringBuilder sb = new StringBuilder();
			HashSet<String> keyword = new HashSet<String>();
			getKeywords(target, keyword);
			int overlap = 0;
			if (!keyword.isEmpty() && !keywordsOfMyMoodContent.isEmpty()) {
				if (keywordsOfMyMoodContent.size() > keyword.size()) {
					for (String key : keyword) {
						if (keywordsOfMyMoodContent.contains(key)) {
							overlap++;
							sb.append(key).append(" ");
						}
					}
				} else {
					for (String key : keywordsOfMyMoodContent) {
						if (keyword.contains(key)) {
							overlap++;
							sb.append(key).append(" ");
						}
					}
				}
				if (overlap > 0) {
					// match =
					// (float)keyword.size()/(keyword.size()+keywordsOfMyMoodContent.size()-overlap);
					// rate = (float)overlap/keyword.size();
					// match *= rate ;
					match = (float) overlap / keywordsOfMyMoodContent.size();
					match = (match * 100 / 100) * 100;
				}
				// logger.info("rate:"+match+",overlap:"+overlap+",target[keyword size:"+keywordsOfMyMoodContent.size()+"]");
			}
		}
		return match;
	}

	@Override
	protected void reIndexDone() {

	}

}